package cn.erbudev;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.HashMap;
import java.util.Map;

import cn.erbudev.CommunicableThread.PairStream;

public class CommunicableThreadManager {
	private Map<Long, CommunicableThread> managerMap;
	private Map<Long, CommunicableThread.PairStream> managerConnectMap;
	private final static Long managerID = -1L;

	public CommunicableThreadManager(int num) {
		super();
		this.managerMap = new HashMap<Long, CommunicableThread>();
		this.managerConnectMap = new HashMap<Long, CommunicableThread.PairStream>();
		init(num);
	}

	private void init(int num) {
		for (Long id = 0L; id < num - 1; id++) {
			PipedOutputStream pipedOutputStream1 = new PipedOutputStream();
			// 创建管道输入流
			PipedInputStream pipedInputStream1 = new PipedInputStream();
			try {
				// 将管道输入流与输出流连接 此过程也可通过重载的构造函数来实现
				pipedOutputStream1.connect(pipedInputStream1);
			} catch (IOException e) {
				e.printStackTrace();
			}
			PipedOutputStream pipedOutputStream2 = new PipedOutputStream();
			// 创建管道输入流
			PipedInputStream pipedInputStream2 = new PipedInputStream();
			try {
				// 将管道输入流与输出流连接 此过程也可通过重载的构造函数来实现
				pipedOutputStream2.connect(pipedInputStream2);
			} catch (IOException e) {
				e.printStackTrace();
			}
			PairStream p1 = new PairStream(pipedOutputStream1, pipedInputStream2);
			PairStream p2 = new PairStream(pipedOutputStream2, pipedInputStream1);
			p1.setBrother(p2);
			CommunicableThread ct = new CommunicableThread(id);
			managerConnectMap.put(id, p1);
			ct.getConnectedMap().put(managerID, p2);
			for (CommunicableThread other : managerMap.values()) {
				ct.addConnectableThread(other);
			}
			managerMap.put(id, ct);
		}
		for (CommunicableThread ct : managerMap.values()) {
			ct.start();
		}

	}

	public void stopAll() {
		for (Map.Entry<Long, CommunicableThread.PairStream> entry : managerConnectMap.entrySet()) {
			ObjectOutputStream outobj;
			try {
				outobj = new ObjectOutputStream(entry.getValue().getOut());
				outobj.writeObject(new FinishTask(managerID, entry.getKey(), null));
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

}
